/*
Problem Description
有N个比赛队（1<=N<=500），编号依次为1，2，3，。。。。，N进行比赛，比赛结束后，裁判委员会要将所有参赛队伍从前往后依次排名，
但现在裁判委员会不能直接获得每个队的比赛成绩，只知道每场比赛的结果，即P1赢P2，用P1，P2表示，排名时P1在P2之前。
现在请你编程序确定排名。
 

Input
输入有若干组，每组中的第一行为二个数N（1<=N<=500），M；其中N表示队伍的个数，M表示接着有M行的输入数据。
接下来的M行数据中，每行也有两个整数P1，P2表示即P1队赢了P2队。
 

Output
给出一个符合要求的排名。输出时队伍号之间有空格，最后一名后面没有空格。

其他说明：符合条件的排名可能不是唯一的，此时要求输出时编号小的队伍在前；输入数据保证是正确的，
即输入数据确保一定能有一个符合要求的排名。
 

Sample Input
4 3
1 2
2 3
4 3
 

Sample Output
1 2 4 3
 */
package com.yuan.algorithms.training20150807;

import java.util.Scanner;

/**
 * @author YouYuan
 * @eMail E-mail:1265161633@qq.com
 * @Time 创建时间：2015年8月11日 上午11:39:48
 * @Explain 说明:本程序默认从编号小的开始排序，所以得出的解便是最小的在前面
 */
public class 拓扑排序_确定比赛名次 {

	static Scanner in = new Scanner(System.in);
	static int MAXN = 501;
	static int n, m;
	static int[][] arc = new int[MAXN][MAXN];// 邻接矩阵，用于储存两个队伍之间的关系
	static boolean[] visited = new boolean[MAXN];// 用于存储当前顶点（队伍）是否已经访问过了
	static int[] degree = new int[MAXN];// 存储每个顶点的入度数（队伍的前驱数）

	public static void main(String[] args) {
		while (in.hasNext()) {
			n = in.nextInt();
			m = in.nextInt();
			initialise();
			structure();
			topologySort();
		}
	}

	/**
	 * 初始化
	 */
	private static void initialise() {
		for (int i = 0; i < n; i++) {
			visited[i] = false;
			degree[i] = 0;
			for (int j = 0; j < n; j++) {
				arc[i][j] = 0;
			}
		}
	}

	/**
	 * 拓扑排序并输出结果
	 */
	private static void topologySort() {
		int sum = 0;//已经排序的顶点数
		while(sum < n) {
			int i;//存储入度为0的顶点的下标
			for (i = 0; i < n; i++) {//查找入度为0并且没有访问过的顶点，即图的起点(排名最靠前的)
				if (degree[i]==0 && !visited[i]) {
					break;
				}
			}
			if (i == n) {//若i==n，说明当前图中无入度为0的顶点，是一个回路
				System.out.println("图中有回路，无解");
				return;
			}
			visited[i] = true;//标记当前顶点已访问
			System.out.print(i+1);//输出编号
			sum++;
			System.out.print(sum < n ? " " : "");
			for (int j = 0; j < n; j++) {
				if (arc[i][j] == 1) {
					degree[j]--;//以当前排序了的顶点为前驱的顶点的入度-1
				}
			}
		}
		System.out.println();
	}

	/**
	 * 构造图
	 */
	private static void structure() {
		
		while (--m >= 0) {
			int a = in.nextInt() - 1;
			int b = in.nextInt() - 1;
			if (arc[a][b] == 0) {//去除重复数据
				arc[a][b] = 1;
				degree[b]++;
			}
		}
	}

}
